#pragma region Description
/*
     Copyright © 2011 Jesse 'LorgonJortle' Wilkerson
     See licensing in source (.cpp) file, or at:
     <http://www.gnu.org/licenses/> (GPL)

     File: Keyboard.h
     Author: Jesse 'LorgonJortle' Wilkerson
     Description:
          Keeping track of all of the keys is easy done with the
          static Keyboard class. It provides a simple IsKeyDown()
          or WasKeyDown() for checking this Update, and checking
          the previous one, too. To check if a key is currently down
          that wasn't down last update, use IsNewKeyDown().
          Along with this header is the Key enumeration, containing
          all of the keys that a player should ever need to press for a
          game. This class is not instantiated, but must be Initialized()
          by Game, which is done automagically.
*/
#pragma endregion

#ifndef KEYBOARD_H
#define KEYBOARD_H

/*****************************************
                              OpenGL
*****************************************/
     #ifdef __APPLE__
         #include <glew.h>
         #include <SDL/SDL.h>
     #else
         #include <GL/glew.h>
         #include <SDL.h>
     #endif
/****************************************/

/*****************************************
                         Standard C++
*****************************************/
     #include <iostream>
     #include <bitset>
/****************************************/

namespace LOGL_GLib
{
     namespace Input
     {
          /* Represents all of the standard keyboard keys. */
          enum Key
          {
               Key_PageUp = SDLK_PAGEUP,
               Key_PageDown = SDLK_PAGEDOWN,
               Key_Home = SDLK_HOME,
               Key_End = SDLK_END,
               Key_Insert = SDLK_INSERT,

               Key_Left = SDLK_LEFT,
               Key_Up = SDLK_UP,
               Key_Right = SDLK_RIGHT,
               Key_Down = SDLK_DOWN,

               Key_F1 = SDLK_F1,
               Key_F2 = SDLK_F2,
               Key_F3 = SDLK_F3,
               Key_F4 = SDLK_F4,
               Key_F5 = SDLK_F5,
               Key_F6 = SDLK_F6,
               Key_F7 = SDLK_F7,
               Key_F8 = SDLK_F8,
               Key_F9 = SDLK_F9,
               Key_F10 = SDLK_F10,
               Key_F11 = SDLK_F11,
               Key_F12 = SDLK_F12,

               Key_A = SDLK_a,
               Key_B = SDLK_b,
               Key_C = SDLK_c,
               Key_D = SDLK_d,
               Key_E = SDLK_e,
               Key_F =SDLK_f,
               Key_G = SDLK_g,
               Key_H = SDLK_h,
               Key_I = SDLK_i,
               Key_J = SDLK_j,
               Key_K = SDLK_k,
               Key_L = SDLK_l,
               Key_M = SDLK_m,
               Key_N = SDLK_n,
               Key_O = SDLK_o,
               Key_P = SDLK_p,
               Key_Q = SDLK_q,
               Key_R = SDLK_r,
               Key_S = SDLK_s,
               Key_T = SDLK_t,
               Key_U = SDLK_u,
               Key_V = SDLK_v,
               Key_W = SDLK_w,
               Key_X = SDLK_x,
               Key_Y = SDLK_y,
               Key_Z = SDLK_z,

               Key_0 = SDLK_0,
               Key_1 = SDLK_1,
               Key_2 = SDLK_2,
               Key_3 = SDLK_3,
               Key_4 = SDLK_4,
               Key_5 = SDLK_5,
               Key_6 = SDLK_6,
               Key_7 = SDLK_7,
               Key_8 = SDLK_8,
               Key_9 = SDLK_9,

               Key_Escape = SDLK_ESCAPE,
               Key_Space = SDLK_SPACE,
               Key_Backspace = SDLK_BACKSPACE,
               Key_Delete = SDLK_DELETE,
               Key_Tab = SDLK_TAB,
               Key_Return = SDLK_RETURN,
               Key_LeftShit = SDLK_LSHIFT,
               Key_RightShift = SDLK_RSHIFT,
               Key_LeftControl = SDLK_LCTRL,
               Key_RightControl = SDLK_RCTRL,
               Key_LeftAlt = SDLK_LALT,
               Key_RightAlt = SDLK_RALT,
               Key_Print = SDLK_PRINT
          }; /* Enum Key. */

          /* The potential states of a key. */
          enum KeyState
          {
               Key_Pressed,
               Key_Released
          }; /* Enum KeyState. */

          /* Static class that maintains the current keyboard state. */
          class Keyboard
          {
          public:
               /* Initializes the keystate buffers and prepares to handle input. */
               static GLvoid Initialize();

               /* Swaps the current/previous keystate buffers. */
               static GLvoid SwapBuffers();

               /* Checks if a key is currently pressed. */
               static GLboolean IsKeyDown(Key _Key);
               /* Checks if a key was pressed last update. */
               static GLboolean WasKeyDown(Key _Key);
               /* Checks if a key is down that wasn't down last update. */
               static GLboolean IsNewKeyDown(Key _Key);
               /* Sets the status of the specified key to pressed (down). */
               static GLvoid KeyDown(GLint _Key);
               /* Sets the status of the specified key to unpressed (up). */
               static GLvoid KeyUp(GLint _Key);
               /* Sets the key action callback. */
               static GLvoid KeyFunc(GLvoid (*_KeyFunc)(Key _Key, KeyState _State));

          private:
               /* The current keystate buffer. */
               static std::bitset<SDLK_LAST> currentKeystate;
               /* The previous keystate buffer (last update). */
               static std::bitset<SDLK_LAST> previousKeystate;
               /* A function pointer to a callback for when a key action occurs. */
               static GLvoid (*keyFunc)(Key _Key, KeyState _State);
          }; /* Class Keyboard. */
     } /* Namespace Input. */
} /* Namespace LOGL_GLib. */

#endif
